package com.skivingcloud.admin.sys.service.impl;

import com.mybatisflex.core.BaseMapper;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.If;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.row.Db;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.skivingcloud.admin.constants.Constant;
import com.skivingcloud.admin.security.SecurityUser;
import com.skivingcloud.admin.security.UserUtil;
import com.skivingcloud.admin.sys.entity.SysRole;
import com.skivingcloud.admin.sys.entity.SysRoleMenu;
import com.skivingcloud.admin.sys.entity.SysTenant;
import com.skivingcloud.admin.sys.mapper.SysRoleMapper;
import com.skivingcloud.admin.sys.mapper.SysRoleMenuMapper;
import com.skivingcloud.admin.sys.service.SysRoleService;
import com.skivingcloud.common.exceptions.BusinessException;
import com.skivingcloud.common.utils.PageParameter;
import com.skivingcloud.common.utils.UuidUtil;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.io.Serializable;
import java.util.Arrays;
import java.util.List;

/**
 *  服务层实现。
 *
 * @author skivingcloud
 * @since 2023-08-28
 */
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService {
    @Resource
    private SysRoleMenuMapper sysRoleMenuMapper;
    /**
     * 分页查询
     *
     * @param parameter 参数
     * @return 查询结果
     */
    @Override
    public Page<SysRole> queryByPage(PageParameter<SysRole> parameter){
        SecurityUser user = UserUtil.getCurrentUser();
        Page<SysRole> page = new Page<>(parameter.getPage(), parameter.getPageSize());
        SysRole sysRole = parameter.getParam();
        QueryWrapper queryWrapper = QueryWrapper.create()
                .from(SysRole.class).as("r").join(SysTenant.class).as("t").on(
                        wrapper -> wrapper.where(SysRole::getTenantId).eq(SysTenant::getId)
                ).where(" 1=1 ");
        if(!Constant.SUPER_ADMIN_TENANT_ID.equals(user.getTenantId())){
            queryWrapper.and(SysRole::getTenantId).eq(user.getTenantId());
        }
        queryWrapper.and(SysTenant::getTenantName).like(sysRole.getTenantName(), If::notNull)
                .and(SysRole::getRoleName).like(sysRole.getRoleName(), If::notNull);
        return this.page(page, queryWrapper);
    }
    
    /**
     * 删除角色
     *
     * @param id 角色id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeByIdRelations(Serializable id){
        Assert.notNull(id,"请传入角色id");
        if(Arrays.stream(Constant.BuiltInRole.values()).anyMatch(r -> r.getValue().equals(id))){
            throw new BusinessException("内置角色，禁止删除！");
        }
        QueryWrapper queryWrapper =   QueryWrapper.create().where(SysRoleMenu::getRoleId).eq(id);
        sysRoleMenuMapper.deleteByQuery(queryWrapper);
        this.mapper.deleteById(id);
    }
    
    /**
     * 新增角色信息
     *
     * @param sysRole 角色信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveHasRes(SysRole sysRole){
        String[] resIds = sysRole.getResId();
        List<SysRoleMenu> list = Arrays.stream(resIds).map(r -> {
            SysRoleMenu sysRoleMenu = new SysRoleMenu();
            sysRoleMenu.setId(UuidUtil.get32UUID());
            sysRoleMenu.setRoleId(sysRole.getId());
            sysRoleMenu.setMenuId(r);
            return sysRoleMenu;
        }).toList();
        //批量插入
        Db.executeBatch(list, Constant.BATCH_SIZE, SysRoleMenuMapper.class, BaseMapper::insert);
        return this.save(sysRole);
    }
    
    /**
     * 修改角色信息
     *
     * @param sysRole 角色信息
     * @return 修改
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByIdHasRes(SysRole sysRole){
        QueryWrapper sm = QueryWrapper.create();
        sm.where(SysRoleMenu::getRoleId).eq(sysRole.getId());
        sysRoleMenuMapper.deleteByQuery(sm);
        String[] resIds = sysRole.getResId();
        List<SysRoleMenu> list = Arrays.stream(resIds).map(r -> {
            SysRoleMenu sysRoleMenu = new SysRoleMenu();
            sysRoleMenu.setId(UuidUtil.get32UUID());
            sysRoleMenu.setRoleId(sysRole.getId());
            sysRoleMenu.setMenuId(r);
            return sysRoleMenu;
        }).toList();
        //批量插入
        Db.executeBatch(list, Constant.BATCH_SIZE, SysRoleMenuMapper.class, BaseMapper::insert);
        return this.updateById(sysRole);
    }
    
    /**
     * 设置角色资源权限
     *
     * @param id    角色ID
     * @param resId 资源权限ID
     */
    @Override
    public void saveRoleRes(String id, String[] resId){
        QueryWrapper sm = QueryWrapper.create();
        sm.where(SysRoleMenu::getRoleId).eq(id);
        sysRoleMenuMapper.deleteByQuery(sm);
        List<SysRoleMenu> list = Arrays.stream(resId).map(r -> {
            SysRoleMenu sysRoleMenu = new SysRoleMenu();
            sysRoleMenu.setId(UuidUtil.get32UUID());
            sysRoleMenu.setRoleId(id);
            sysRoleMenu.setMenuId(r);
            return sysRoleMenu;
        }).toList();
        //批量插入
        Db.executeBatch(list, Constant.BATCH_SIZE, SysRoleMenuMapper.class, BaseMapper::insert);
    }
    
    /**
     * 根据租户id获取所有角色
     *
     * @param tenantId 租户id
     * @return 角色
     */
    @Override
    public List<SysRole> listByTenantId(String tenantId){
        QueryWrapper queryWrapper = QueryWrapper.create().where(SysRole::getTenantId).eq(tenantId);
        return this.list(queryWrapper);
    }
}
